package com.ee.chat.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ee.chat.api.common.CommonService;
import com.ee.chat.api.service.ILoginService;
import com.ee.chat.api.service.IUserService;
import com.ee.chat.common.bean.Result;
import com.ee.chat.common.dao.*;
import com.ee.chat.common.entity.*;
import com.ee.chat.common.serconfig.MyAliOSSConfig;
import com.ee.chat.common.serconfig.MyNeteaseApp;
import com.ee.chat.common.serconfig.MyWXOAuthConfig;
import com.ee.chat.common.service.IGeneralService;
import com.ee.chat.common.service.IPushMessageService;
import com.ee.chat.common.service.IYieldService;
import com.ee.chat.common.util.ConstantsUtil;
import com.ndhutu.ee.util.DateUtil;
import com.ndhutu.ee.util.StringUtil;
import com.ndhutu.ee.util.ValidatorUtil;
import com.ndhutu.ee.util.netease.im.IMUtil;
import com.ndhutu.ee.util.oauth.wx.WXOAuthUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Resource(name = "stringRedisTemplate")
    StringRedisTemplate redisTemplate;
    @Resource
    UserMapper userMapper;
    @Resource
    HostMapper hostMapper;
    @Resource
    IUserService userService;
    @Resource
    ChannelMapper channelMapper;
    @Resource
    BaseMapper baseMapper;
    @Resource
    MyNeteaseApp app;
    @Resource
    MyAliOSSConfig ossConfig;
    @Resource
    UserOperationLogMapper userOperationLogMapper;
    @Resource
    ChannelUserLogMapper channelUserLogMapper;
    @Resource
    IPushMessageService pushMessageService;
    @Resource
    CommonService commonService;
    @Resource
    IGeneralService generalService;
    @Resource
    IYieldService yieldService;
    @Resource
    MyWXOAuthConfig wxoAuthConfig;
    @Resource
    UserAuditLogMapper userAuditLogMapper;
    @Resource
    UserInviteLogMapper userInviteLogMapper;
    @Resource
    UserExpandMapper userExpandMapper;
    @Resource
    UserSealLogMapper userSealLogMapper;
    @Resource
    UserOnlineLogMapper userOnlineLogMapper;
    @Resource
    SysConfigMapper sysConfigMapper;
    @Resource
    DisableImeiMapper imeiMapper;
    @Resource
    UserSetMapper userSetMapper;

    @Override
    @Transactional
    public Result login(HttpServletRequest request, Integer type, String thirdId, String name, String icon, String code,
                        String inviteCode, String channelCode, String channelCode2, String extra) throws Exception {
        Map<String, Object> data = new HashMap<>();

        User user = null;
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        String codeKey = null;
        if(type == 0){  //手机号登录注册
            if(!ValidatorUtil.verifyPhone(thirdId)){
                return Result.returnFailure("请输入正确的手机号");
            }

            codeKey = ConstantsUtil.DATA_CODE + "login:" + thirdId;
            Object value = redisTemplate.opsForHash().get(codeKey, "code");
            if(value == null || !code.equals(value)){
                return Result.returnFailure("验证码错误");
            }

            user = userMapper.selectByPhone(thirdId);

        }else if(type == 1){    //qq登录注册
            wrapper.eq("qq_unionid", thirdId);

        }else if(type == 2){    //微信登录注册
            wrapper.eq("wx_unionid", thirdId);

        }else{
            return Result.returnFailure("非法参数");
        }

        //判断账号状态
        if(wrapper.getSqlSelect() != null){
            user = userMapper.selectOne(wrapper);
        }
        if(user != null && user.getStatus() == 1){
            UserSealLog userSealLog = userSealLogMapper.selectNewestLog(user.getId());
            String desc = "账号已被禁用，详情请咨询客服";
            if(userSealLog != null){
                if(userSealLog.getHour() == 0){
                    desc = "您的账号因："+userSealLog.getReason()+"已被永久禁用，详情请咨询客服";
                }else{
                    desc = "您的账号因为在"+DateUtil.format(userSealLog.getCreateTime())+"时被处以封禁"+userSealLog.getHour()+"小时处罚，请封禁结束后再使用，详情请咨询客服";
                }
            }
            return Result.returnFailure(desc);
        }

        //判断设备状态
        Map<String, Object> extraMap = JSONObject.parseObject(extra);
        String imei = null;
        if(!StringUtil.isEmpty(extraMap.get("imei"))){
            imei = extraMap.get("imei")+"";
            //判断设备号是否被封禁
            DisableImei disableImei = imeiMapper.getDisableImei(imei);
            if(disableImei != null){
                return Result.returnFailure("您的设备已被禁用，详情请咨询客服");
            }
        }

        Map<String, Object> map = new HashMap<>();
        String token = StringUtil.getUUIDStr();
        if(user == null){   //注册

            //注册过主播的设备，不能再注册其他账号
            if(imei != null){
                int count = userMapper.selectHostByImei(imei);
                if(count > 0){
                    return Result.returnFailure("该设备已注册过主播账号，无法再进行注册");
                }
            }

            user = new User();
            user.setId(generalService.getNewUserId());
            user.setInviteCode(generalService.getNewInviteCode());
            user.setToken(token);
            if(type == 0){
                user.setPhone(thirdId);
            }else if(type == 1){
                user.setQqUnionid(thirdId);
            }else if(type == 2){
                user.setWxUnionid(thirdId);
            }

            //默认头像和昵称均为系统分配
            name = baseMapper.getRandomUserName();
            icon = baseMapper.getRandomUserIcon();

            user.setName(name);
            user.setIcon(icon);
            user.setOnline(3);  //在线
            Date now = new Date();
            user.setCreateTime(now);
            user.setUpdateTime(now);
            user.setImei(imei);

            //网易IM注册
            String imToken = "123456";
            String ossUrl = "https://"+ossConfig.getBucketName()+"."+ossConfig.getEndpoint()+"/";
            try {
                IMUtil.create(app.getIdPrefix()+user.getId(), name, ossUrl+icon, imToken, app);
            } catch(Exception e){
                IMUtil.update(app.getIdPrefix()+user.getId(), imToken, app);
                IMUtil.updateUinfo(app.getIdPrefix()+user.getId(), name, ossUrl+icon, null, app);
            }
            user.setImToken(imToken);
            userMapper.insert(user);

            //处理邀请绑定
            generalService.handleInviteBind(request, user.getId(), imei, inviteCode, channelCode, channelCode2);

            //推送消息
            pushMessageService.pushNewUserMessage(user.getId());

            map.put("must", 1);    //必须绑定性别等信息

        } else {    //登录
            //踢掉用户
            redisTemplate.expire(ConstantsUtil.USER_TOKEN + user.getToken(), -1, TimeUnit.MINUTES);

            //更新token
            user.setToken(token);
            user.setUpdateTime(new Date());
            UserSet userSet = userSetMapper.selectByUserId(user.getId());
            if(userSet != null && userSet.getDnd() == 1){
                user.setOnline(1);  //勿扰
            }else{
                user.setOnline(3);  //在线
            }
            userMapper.updateById(user);

            if(user.getGender() == 0){
                map.put("must", 1);
            }else{
                map.put("must", 0);
            }
        }

        //缓存用户id
        String key = ConstantsUtil.USER_TOKEN + token;
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("userId", user.getId()+"");
        tokenMap.put("extra", extra);
        redisTemplate.opsForHash().putAll(key, tokenMap);
        redisTemplate.expire(key, 365, TimeUnit.DAYS);

        //删除验证码
        if(codeKey != null){
            redisTemplate.expire(codeKey, -1, TimeUnit.MINUTES);
        }

        map.put("id", user.getId());
        map.put("token", user.getToken());
        map.put("imToken", user.getImToken());
        Host host = hostMapper.selectByUserId(user.getId());
        map.put("host", host == null ? 0 : 1);

        if(map.get("must").equals(1)){
            map.put("icon", user.getIcon());
            map.put("name", user.getName());
            map.put("gender", 1);
            map.put("default_man_icon", sysConfigMapper.getValue("default_man_icon"));
            map.put("default_woman_icon", sysConfigMapper.getValue("default_woman_icon"));
        }
        data.put("user", map);

        log.info(user.getId()+"登录成功");
        return Result.returnSuccess(data);
    }

    @Override
    public Result logout(String token) throws Exception {
        Integer userId = commonService.getUserId(token);

        User user = userMapper.selectById(userId);
        user.setOnline(0);
        userMapper.updateById(user);

        //删除token
        String key = ConstantsUtil.USER_TOKEN + token;
        redisTemplate.expire(key, -1, TimeUnit.MINUTES);

        //删除在线
        key = ConstantsUtil.USER_ONLINE + userId;
        redisTemplate.expire(key, -1, TimeUnit.MINUTES);

        //下线记录时间
        UserOnlineLog userOnlineLog = userOnlineLogMapper.selectNewestLog(userId);
        userOnlineLog.setDownTime(new Date());
        userOnlineLogMapper.updateById(userOnlineLog);

        return Result.returnSuccess(null);
    }

    @Override
    public Result batchRegisterIM() throws Exception {
        List<User> users = userMapper.selectList(null);
        String ossUrl = "https://"+ossConfig.getBucketName()+"."+ossConfig.getEndpoint()+"/";

        for(User user : users){
            IMUtil.create(app.getIdPrefix()+user.getId(), user.getName(), ossUrl+user.getIcon(), user.getImToken(), app);
        }

        return Result.returnSuccess(null);
    }

    /**
     * 获取授权唯一标识
     * @Author Shane
     * @Date 2020/5/30 0:45
     * @param type 授权类型，2-微信
     * @param code  type=2时必传
     * @return
     */
    @Override
    public Result getAuthInfo(Integer type, String code) throws Exception {
        Map<String, Object> data = new HashMap<>();

        if(type == 2){
            if(StringUtil.isEmpty(code)){
                return Result.returnFailure("code不能为空");
            }

            Map<String, Object> accessTokenMap = WXOAuthUtil.getAccessToken(code, wxoAuthConfig);
            if(StringUtil.isEmpty(accessTokenMap.get("errcode"))){
                log.info("微信授权失败："+JSONObject.toJSONString(accessTokenMap));
                return Result.returnFailure();
            }

            String openid = accessTokenMap.get("openid")+"";
            String accessToken = accessTokenMap.get("access_token")+"";
            Map<String, Object> userInfoMap = WXOAuthUtil.getUserInfo(accessToken, openid);
            if(StringUtil.isEmpty(userInfoMap.get("errcode"))){
                log.info("微信获取个人信息失败："+JSONObject.toJSONString(accessTokenMap));
                return Result.returnFailure();
            }

            data.put("wx", userInfoMap);

        }else{
            return Result.retuenIllegality();
        }

        return Result.returnSuccess(data);
    }

    @Override
    public Result updateUserInfo(String token, String icon, String name, Integer gender) throws Exception {
        Integer userId = commonService.getUserId(token);

        UserAuditLog userAuditLog = userAuditLogMapper.selectAccecpt(userId, 2);
        if(userAuditLog != null){
            return Result.returnFailure("信息已经提交待审核，请勿重复提交");
        }

        if(StringUtil.isEmpty(icon)){
            return Result.returnFailure("头像为必填信息");
        }
        if(StringUtil.isEmpty(name.trim())){
            return Result.returnFailure("昵称为必填信息");
        }
        if(name.length() > 12){
            return Result.returnFailure("用户昵称不能超过12个字符");
        }

        String default_man_icon = sysConfigMapper.getValue("default_man_icon");
        String default_woman_icon = sysConfigMapper.getValue("default_woman_icon");

        boolean flag = true;
        userAuditLog = new UserAuditLog();

        if(!(default_man_icon.equals(icon) || default_woman_icon.equals(icon) || baseMapper.getUserIconCount(icon) == 1)){
            userAuditLog.setIcon(icon);
            flag &= false;
        }
        if(baseMapper.getUserNameCount(name) != 1){
            userAuditLog.setName(name);
            flag &= false;
        }
        if(!flag){
            userAuditLog.setType(2);
            userAuditLog.setUserId(userId);
            userAuditLogMapper.insert(userAuditLog);
        }

        //更新性别
        User user = userMapper.selectById(userId);
        if(user.getGender() != 0){
            return Result.returnFailure("不可重复调用接口");
        }
        user.setGender(gender);

        //更新头像
        if(gender == 0){
            icon = default_woman_icon;
        }else{
            icon = default_man_icon;
        }
        user.setIcon(icon);
        userMapper.updateById(user);
        String ossUrl = "https://"+ossConfig.getBucketName()+"."+ossConfig.getEndpoint()+"/";
        IMUtil.updateUinfo(app.getIdPrefix()+userId, null, ossUrl+icon, gender, app);

        //处理邀请注册奖励
        yieldService.handleInviteRegYield(user.getId());

        return Result.returnSuccess(null);
    }
}
